"""
任务状态检查服务 - 通过ARQ Redis检查子任务状态
"""
import redis
from typing import List, Dict, Any, Optional
from axiom_boot.di import service, autowired
from axiom_boot.logging.setup import get_logger
from axiom_boot.conf import Settings

from .scraper_task_service import ScraperTaskService

logger = get_logger(__name__)


@service()
class TaskStatusChecker:
    """任务状态检查器 - 检查ARQ子任务状态并更新主任务"""
    
    def __init__(self, 
                 settings: Settings = autowired(),
                 scraper_task_service: ScraperTaskService = autowired()):
        self.settings = settings
        self.scraper_task_service = scraper_task_service
        self._redis_client = None
    
    def _get_redis_client(self) -> redis.Redis:
        """获取Redis客户端"""
        if self._redis_client is None:
            # 从设置中获取Redis连接信息
            redis_url = getattr(self.settings, 'redis_url', 'redis://localhost:6379/0')
            self._redis_client = redis.from_url(redis_url, decode_responses=True)
        return self._redis_client
    
    async def check_subtasks_status(self, main_task_id: str, job_ids: List[str]) -> Dict[str, Any]:
        """
        检查子任务状态
        
        Args:
            main_task_id: 主任务ID
            job_ids: 子任务job_id列表
            
        Returns:
            {
                "total_jobs": int,
                "in_progress": int,
                "in_retry": int,
                "completed_or_failed": int,
                "all_stopped": bool,
                "job_details": {...}
            }
        """
        redis_client = self._get_redis_client()
        
        result = {
            "total_jobs": len(job_ids),
            "in_progress": 0,
            "in_retry": 0,
            "completed_or_failed": 0,
            "all_stopped": False,
            "job_details": {}
        }
        
        try:
            for job_id in job_ids:
                job_status = {
                    "job_id": job_id,
                    "in_progress": False,
                    "in_retry": False,
                    "has_job_record": False
                }
                
                # 检查是否在进行中
                in_progress_key = f"arq:in-progress_{job_id}"
                if redis_client.exists(in_progress_key):
                    job_status["in_progress"] = True
                    result["in_progress"] += 1
                
                # 检查是否在重试队列
                retry_key = f"arq:retry:{job_id}"
                if redis_client.exists(retry_key):
                    job_status["in_retry"] = True
                    result["in_retry"] += 1
                
                # 检查是否有job记录
                job_key = f"arq:job:{job_id}"
                if redis_client.exists(job_key):
                    job_status["has_job_record"] = True
                
                # 如果都不存在，认为已完成或失败
                if not (job_status["in_progress"] or job_status["in_retry"] or job_status["has_job_record"]):
                    result["completed_or_failed"] += 1
                
                result["job_details"][job_id] = job_status
            
            # 判断是否所有任务都已停止
            result["all_stopped"] = (result["completed_or_failed"] == result["total_jobs"])
            
            logger.info(f"【{main_task_id}】子任务状态检查: 总计{result['total_jobs']}, "
                       f"进行中{result['in_progress']}, 重试中{result['in_retry']}, "
                       f"已停止{result['completed_or_failed']}, 全部停止: {result['all_stopped']}")
            
        except Exception as e:
            logger.error(f"【{main_task_id}】检查子任务状态失败: {e}")
            result["error"] = str(e)
        
        return result
    
    async def update_main_task_if_completed(self, main_task_id: str) -> bool:
        """
        检查并更新主任务状态（如果所有子任务都已停止）
        
        Returns:
            bool: 是否更新了主任务状态
        """
        try:
            # 获取主任务记录
            task_record = await self.scraper_task_service.find_one_by_filters(task_id=main_task_id)
            if not task_record:
                logger.warning(f"未找到主任务记录: {main_task_id}")
                return False
            
            # 检查任务状态，只处理running状态的任务
            if task_record.task_status != "running":
                logger.debug(f"【{main_task_id}】任务状态非running，跳过: {task_record.task_status}")
                return False
            
            # 获取子任务job_ids
            job_ids = task_record.config_params.get("sub_job_ids", [])
            if not job_ids:
                logger.warning(f"【{main_task_id}】未找到子任务job_ids，直接标记为完成")
                await self._complete_main_task(main_task_id, task_record)
                return True
            
            # 检查子任务状态
            status_result = await self.check_subtasks_status(main_task_id, job_ids)
            
            if status_result["all_stopped"]:
                logger.info(f"【{main_task_id}】所有子任务已停止，更新主任务状态")
                await self._complete_main_task(main_task_id, task_record)
                return True
            else:
                logger.debug(f"【{main_task_id}】仍有子任务运行中，暂不更新主任务状态")
                return False
                
        except Exception as e:
            logger.error(f"【{main_task_id}】更新主任务状态失败: {e}")
            return False
    
    async def _complete_main_task(self, main_task_id: str, task_record) -> None:
        """完成主任务"""
        try:
            # 计算最终统计信息
            final_stats = {
                "total_processed": task_record.total_processed or 0,
                "success_count": task_record.success_count or 0,
                "failed_count": task_record.failed_count or 0,
                "success_rate": task_record.success_rate or 0.0
            }
            
            await self.scraper_task_service.complete_task(
                task_id=main_task_id,
                final_stats=final_stats
            )
            
            logger.info(f"【{main_task_id}】主任务已标记为完成")
            
        except Exception as e:
            logger.error(f"【{main_task_id}】完成主任务失败: {e}")
            raise
    
    async def check_and_update_all_running_tasks(self) -> Dict[str, Any]:
        """
        检查并更新所有running状态的主任务
        用于定时扫描
        """
        try:
            # 获取所有running状态的任务
            running_tasks = await self.scraper_task_service.find_by_filters(task_status="running")
            
            result = {
                "total_checked": len(running_tasks),
                "updated_count": 0,
                "updated_tasks": [],
                "errors": []
            }
            
            for task in running_tasks:
                try:
                    updated = await self.update_main_task_if_completed(task.task_id)
                    if updated:
                        result["updated_count"] += 1
                        result["updated_tasks"].append(task.task_id)
                except Exception as e:
                    error_info = {"task_id": task.task_id, "error": str(e)}
                    result["errors"].append(error_info)
                    logger.error(f"检查任务{task.task_id}失败: {e}")
            
            logger.info(f"运行状态任务检查完成: 检查{result['total_checked']}个, "
                       f"更新{result['updated_count']}个, 错误{len(result['errors'])}个")
            
            return result
            
        except Exception as e:
            logger.error(f"批量检查运行状态任务失败: {e}")
            return {"error": str(e)}
